﻿' LibWowArmory
' by Ronald M. Clifford (roncli@roncli.com)
'
' This source code is released under the GNU Library General Public License (LGPL) Version 2.1.

Imports System
Imports System.Collections
Imports System.Globalization
Imports System.IO
Imports System.Net
Imports System.Reflection
Imports System.Security
Imports System.Text
Imports System.Threading
Imports System.Web

<Assembly: CLSCompliant(True)> 

Namespace roncliProductions.LibWowArmory

    ''' <summary>
    ''' The base class to inherit Armory info from
    ''' </summary>
    ''' <remarks></remarks>
    Public MustInherit Class WowArmoryData

        Protected Property Data As String

        ''' <summary>
        ''' The URL that will open the appropriate armory page
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public MustOverride ReadOnly Property URL As String

        ''' <summary>
        ''' A boolean value that determines whether or not you are required to login to the Armory before accessing the data
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public MustOverride ReadOnly Property RequiresLogin As Boolean

        ''' <summary>
        ''' The username of the account you wish to log in to the Armory with
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Username As String

        ''' <summary>
        ''' The password of the account you wish to log in to the Armory with
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Password As String

        Private Shared Property ArmoryCookie As CookieContainer
            Get
                If Cache.Cache("LibWoWArmory.ArmoryCookie") Is Nothing Then
                    Return New CookieContainer
                End If
                Dim ccCookies As CookieContainer = CType(Cache.Cache("LibWoWArmory.ArmoryCookie"), CookieContainer)
                Dim htCookies As Hashtable = CType(ccCookies.GetType.InvokeMember("m_domainTable", BindingFlags.NonPublic Or BindingFlags.GetField Or BindingFlags.Instance, Nothing, ccCookies, New Object() {}, CultureInfo.InvariantCulture), Hashtable)
                For Each strKey As String In New ArrayList(htCookies.Keys)
                    If strKey.StartsWith(".", StringComparison.Ordinal) Then
                        htCookies(strKey.Substring(1)) = htCookies(strKey)
                    End If
                Next
                Return ccCookies
            End Get
            Set(ByVal value As CookieContainer)
                Cache.Cache.Insert("LibWoWArmory.ArmoryCookie", value, Nothing, Date.UtcNow.AddDays(1), Nothing, Caching.CacheItemPriority.NotRemovable, Nothing)
            End Set
        End Property

        ''' <summary>
        ''' Retrieves the data based on the supplied query
        ''' </summary>
        ''' <remarks></remarks>
        Protected Sub Retrieve()
            If RequiresLogin Then
                If Not CheckLogin Then
                    ArmoryLogin(Username, Password)
                    If Not CheckLogin Then
                        Throw New SecurityException("You could not be logged in to the Armory.  Check your username and password.")
                        Exit Sub
                    End If
                End If
            End If

            Dim hwrRequest As HttpWebRequest = CType(HttpWebRequest.Create(URL), HttpWebRequest)
            hwrRequest.Accept = "*/*"
            hwrRequest.UserAgent = "MSIE 7.0"
            hwrRequest.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-us")
            hwrRequest.Headers.Add(HttpRequestHeader.Pragma, "no-cache")
            hwrRequest.CookieContainer = ArmoryCookie
            hwrRequest.Timeout = 10000
            Try
                Using wrResponse As WebResponse = hwrRequest.GetResponse
                    Using srReader As New StreamReader(wrResponse.GetResponseStream)
                        Data = srReader.ReadToEnd
                    End Using
                    For Each cCookie As Cookie In CType(wrResponse, HttpWebResponse).Cookies
                        hwrRequest.CookieContainer.Add(cCookie)
                    Next
                    ArmoryCookie = hwrRequest.CookieContainer
                End Using
            Catch wex As WebException
                If wex.Response Is Nothing Then Throw
                If CType(wex.Response, HttpWebResponse).StatusCode = HttpStatusCode.NotFound Then
                    Data = ""
                Else
                    Throw
                End If
            End Try
            hwrRequest = Nothing
        End Sub

        Private Shared Sub ArmoryLogin(ByVal strUsername As String, ByVal strPassword As String)
            Dim hwrRequest As HttpWebRequest = CType(HttpWebRequest.Create("http://www.wowarmory.com/?login=1"), HttpWebRequest)
            hwrRequest.Accept = "*/*"
            hwrRequest.UserAgent = "MSIE 7.0"
            hwrRequest.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-us")
            hwrRequest.Headers.Add(HttpRequestHeader.Pragma, "no-cache")
            hwrRequest.CookieContainer = ArmoryCookie
            hwrRequest.Timeout = 10000
            Using wrResponse As WebResponse = hwrRequest.GetResponse
                Using srReader As New StreamReader(wrResponse.GetResponseStream)
                    srReader.ReadToEnd()
                End Using
                For Each cCookie As Cookie In CType(wrResponse, HttpWebResponse).Cookies
                    hwrRequest.CookieContainer.Add(cCookie)
                Next
                ArmoryCookie = hwrRequest.CookieContainer
            End Using
            hwrRequest = Nothing

            hwrRequest = CType(HttpWebRequest.Create("https://us.battle.net/login/login.xml?ref=http%3A%2F%2Fwww.wowarmory.com%2Findex.xml&app=armory"), HttpWebRequest)
            hwrRequest.Accept = "*/*"
            hwrRequest.UserAgent = "MSIE 7.0"
            hwrRequest.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-us")
            hwrRequest.Headers.Add(HttpRequestHeader.Pragma, "no-cache")
            hwrRequest.CookieContainer = ArmoryCookie
            hwrRequest.Timeout = 10000
            Dim strPostData As String = String.Format(CultureInfo.InvariantCulture, "accountName={0}&password={1}", HttpUtility.UrlEncode(strUsername), HttpUtility.UrlEncode(strPassword))
            Dim bytPostData() As Byte = Encoding.ASCII.GetBytes(strPostData)
            hwrRequest.Method = "POST"
            hwrRequest.ContentType = "application/x-www-form-urlencoded"
            hwrRequest.ContentLength = bytPostData.Length
            Using sStream As Stream = hwrRequest.GetRequestStream
                sStream.Write(bytPostData, 0, bytPostData.Length)
            End Using
            Using wrResponse As WebResponse = hwrRequest.GetResponse
                Using srReader As New StreamReader(wrResponse.GetResponseStream)
                    srReader.ReadToEnd()
                End Using
                For Each cCookie As Cookie In CType(wrResponse, HttpWebResponse).Cookies
                    hwrRequest.CookieContainer.Add(cCookie)
                Next
                ArmoryCookie = hwrRequest.CookieContainer
            End Using
            hwrRequest = Nothing
        End Sub

        Private Shared Function CheckLogin() As Boolean
            Dim lsStatus As New LoginStatus.LoginStatus
            Return Not String.IsNullOrEmpty(lsStatus.LoggedInUsername)
        End Function

    End Class

End Namespace